package com.ma.security;

import cn.hutool.core.util.StrUtil;
import com.ma.entity.SysUser;
import com.ma.service.SysUserService;
import com.ma.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/*
    自定义一个过滤器用来进行识别jwt
    获取到用户名之后我们直接把封装成UsernamePasswordAuthenticationToken，
    之后交给SecurityContextHolder参数传递authentication对象，这样后续security就能获取到当前登录的用户信息了，也就完成了用户认证。
 */
@Slf4j
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private UserDetalisServiceImpl userDetalisService;
    @Autowired
    private SysUserService userService;
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("jwt 校验 filter");
        String jwt=request.getHeader(jwtUtils.getHeard());
        //如果jwt为空 则放行不需要登录的路径 如 登录页面  静态资源 白名单等
        if (StrUtil.isBlankOrUndefined(jwt)){
            chain.doFilter(request,response);
            return;
        }
        //有jwt的情况 需要解析jwt
        Claims claims=jwtUtils.getClaimsByToken(jwt);
        if (claims ==null){
            //如果为空 则解析失败 抛出异常
            new JwtException("token 异常");
        }
        if (jwtUtils.isTokenExpried(claims)){
            new JwtException("token 已过期");
        }
        //进去自动登录步骤
        //从主体中获取用户名
        String username = claims.getSubject();
        log.info("用户-{}，正在登陆！", username);
        SysUser sysUser =userService.getAllByUsername(username);
        //获取用户权限等信息                                                                  自动登录 故密码为空  权限信息 接口调用进行身份认证过滤器时候JWTAuthenticationFilter，需要返回用户权限信息
        UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(username,null,userDetalisService.getUserAuthority(sysUser.getId()));
        //  之后交给SecurityContextHolder参数传递authentication对象，这样后续security就能获取到当前登录的用户信息了，也就完成了用户认证。
        SecurityContextHolder.getContext().setAuthentication(token);
        chain.doFilter(request,response);
    }
}
